package com.lagou.edu.servlet;

import com.lagou.edu.annotation.MyAutowired;
import com.lagou.edu.annotation.MyService;
import com.lagou.edu.annotation.MyTransactional;
import com.lagou.edu.factory.ProxyFactory;
import com.lagou.edu.pojo.Result;
import com.lagou.edu.service.TransferService;
import com.lagou.edu.utils.JsonUtils;
import org.reflections.Reflections;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author 应癫
 */
@WebServlet(name = "transferServlet", urlPatterns = "/transferServlet")
public class TransferServlet extends HttpServlet {

    private TransferService transferService = null;

    /** 存储扫描对象 */
    public Map<String, Object> beanMap = new HashMap<>();

    @Override
    public void init() throws ServletException {

        getObjectMap();

        transferService = (TransferService) beanMap.get("transferService");

    }

    /** 扫描对象 并存储 */
    private void getObjectMap() {
        try {

            // 1.扫描获取 MyService注解 反射对象集合
            Reflections reflections = new Reflections("com.lagou.edu");
            Set<Class<?>> servecesTypesAnnotatedWith = reflections.getTypesAnnotatedWith(MyService.class);
            for (Class<?> c : servecesTypesAnnotatedWith) {
                //实例化对象
                Object bean = c.getDeclaredConstructor().newInstance();

                MyService annotation = c.getAnnotation(MyService.class);
                if (StringUtils.isEmpty(annotation.value())) {
                    //注解 无 value 属性
                    // System.out.println(c.getSimpleName());
                    System.out.println("========MyService========" + c.getSimpleName());
                    beanMap.put(c.getSimpleName(), bean);
                } else {
                    //注解 有 value 属性
                    System.out.println("========MyService========" + annotation.value());
                    beanMap.put(annotation.value(), bean);
                }
            }

            // 2.注入 对象的依赖属性 @MyAutowired
            for (Map.Entry<String, Object> beanMapEntry : beanMap.entrySet()) {
                Object bean = beanMapEntry.getValue();
                Class<?> c = bean.getClass();

                //获取对象所有变量
                Field[] declaredFields = c.getDeclaredFields();
                //遍历找到 有 MyAutowired 注解属性
                for (Field declaredField : declaredFields) {
                    if (declaredField.isAnnotationPresent(MyAutowired.class) && declaredField.getAnnotation(MyAutowired.class).required()) {
                        String autowiredName = declaredField.getName();

                        Method[] methods = c.getMethods();
                        for (Method method : methods) {
                            // 找对对应的set方法 如：setAccountDao(AccountDao accountDao)
                            if (method.getName().equalsIgnoreCase("set" + autowiredName)) {
                                 System.out.println("========autowired========" + declaredField.getName());
                                // 执行set方法
                                method.invoke(bean, beanMap.get(autowiredName));
                            }
                        }

                    }
                }

                //3. 判断是否有 MyTransactional 注解
                if (c.isAnnotationPresent(MyTransactional.class)) {
                    //获取代理工厂d
                    ProxyFactory proxyFactory = (ProxyFactory) beanMap.get("ProxyFactory");
                    //获取类c实现的所有接口
                    Class[] face = c.getInterfaces();
                    //判断对象是否实现接口
                    if (face != null && face.length > 0) {
                        //实现使用JDK
                        bean = proxyFactory.getJdkProxy(bean);
                    } else {
                        //没实现使用CGLIB
                        bean = proxyFactory.getCglibProxy(bean);
                    }
                }
                beanMap.put(beanMapEntry.getKey(), bean);
            }


        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 设置请求体的字符编码
        req.setCharacterEncoding("UTF-8");

        String fromCardNo = req.getParameter("fromCardNo");
        String toCardNo = req.getParameter("toCardNo");
        String moneyStr = req.getParameter("money");
        int money = Integer.parseInt(moneyStr);

        Result result = new Result();

        try {

            // 2. 调用service层方法
            transferService.transfer(fromCardNo, toCardNo, money);
            result.setStatus("200");
        } catch (Exception e) {
            e.printStackTrace();
            result.setStatus("201");
            result.setMessage(e.toString());
        }

        // 响应
        resp.setContentType("application/json;charset=utf-8");
        resp.getWriter().print(JsonUtils.object2Json(result));
    }
}
